use shellexpand::full;
use std::fs::copy;
use std::fs::create_dir;
use std::fs::read;
use std::path::PathBuf;
use std::thread;
use std::time;
use structopt::StructOpt;

const VAULT_PATH: &str = "~/.cache/insurefile";
const HOUR_SECS: u64 = 3600;

#[derive(Debug, StructOpt)]
struct Opt {
    /// A tag to view, without # (because bash)
    #[structopt()]
    path: String,
}

fn read_unix(filename: &str) -> Result<String, Box<dyn std::error::Error>> {
    let path = full(filename)?.to_string();
    return Ok(String::from_utf8(read(path)?)?);
}

fn vault_path() -> String {
    let vault_path = full(VAULT_PATH)
        .expect("cannot expand the vault path")
        .to_string();
    return vault_path;
}

fn cached_path(path: &str) -> String {
    return vault_path() + "/cached_" + &path.replace("/", "\\");
}

fn ensure_vault_exists() {
    let vault_path_buf = PathBuf::from(vault_path());
    if !vault_path_buf.exists() {
        let _res = create_dir(vault_path_buf).expect("cannot create vault dir!");
    }
}

fn file_is_empty(filename: &str) -> bool {
    let filestring = read_unix(filename).expect("could not read the file");
    if filestring.replace(" ", "").replace("\n", "").len() == 0 {
        return true;
    };
    return false;
}

fn insure(path: &str) {
    if !file_is_empty(&path) {
        copy(&path, cached_path(&path)).expect("could not copy!");
    }
}

fn main() {
    let opt = Opt::from_args();
    let path = opt.path;
    ensure_vault_exists();

    let sleep_duration = time::Duration::from_secs(2 * HOUR_SECS);
    loop {
        insure(&path);
        thread::sleep(sleep_duration);
    }
}
